import UnchangedExpression from "../impl/UnchangedExpression";
import OrderByExpression from "../OrderByExpression";
import ExtendExpression from "./ExtendExpression";
import MetaData from "../MetaData";
import FieldExpression from "../impl/FieldExpression";

/** 表达式接口 */
abstract class BaseExpression extends ExtendExpression {

    /** 排序 */
    public orderBy(field: string, sort: "DESC" | "ASC" = 'DESC'): BaseExpression {
        return new OrderByExpression(this.metadata, new UnchangedExpression(`ORDER BY ${field} ${sort}`)) as unknown as BaseExpression;
    }

    /** 默认自减，第二个参数为需要减的数 */
    public async decrement(field: string, number: number = 1): Promise<number> {
        this.metadata.type = MetaData.UPDATE;
        field = new FieldExpression(field, "", this.metadata).toLocaSql();
        this.metadata.add(new UnchangedExpression(`set ${field}=${field}-${number}`), 1);
        return this.metadata.core.select(this.metadata);
    }

    /** 默认自增，第二个参数为需要减的数 */
    public increment(field: string, number: number = 1): Promise<number> {
        this.metadata.type = MetaData.UPDATE;
        field = new FieldExpression(field, "", this.metadata).toLocaSql();
        this.metadata.add(new UnchangedExpression(`set ${field}=${field}+${number}`), 1);
        return this.metadata.core.select(this.metadata);
    }

    /** 计数器 */
    public count(field?: string): Promise<number> {
        field = field ? new FieldExpression(field, "", this.metadata).toLocaSql() : "*";
        this.metadata.fields = `count(${field}) as count`;
        this.metadata.add(new UnchangedExpression("select " + this.metadata.fields + " from", this.metadata), 0)
        return this.metadata.core.select<any[]>(this.metadata).then(e => e[0]?.count);
    }

    /** 原生语句 */
    public native(sql: string, parameter: any[] = []) {
        this.metadata.add(new UnchangedExpression(sql, this.metadata));
        this.metadata.parameter.push(...parameter);
        return this;
    }

    /** 子查询 */
    public subquery(callback: (table: BaseExpression) => any, alias: string = "") {
        ExtendExpression.subqueryFactory<BaseExpression>(this, this.metadata, callback, alias)
    }

}

export = BaseExpression;